

#include "rviz_custom_plugins/utils/project_manager.h"
#include <QFileInfo>
#include <QFile>
#include <QStringList>
#include <QJsonDocument>
#include <QJsonObject>
#include <QDir>
#include <rviz_common/logging.hpp>
#include "rviz_custom_plugins/utils/file_util.h"
#include <QDebug>


namespace rviz_custom_plugins
{

namespace utils
{


// 静态成员初始化
QPointer<ProjectManager> ProjectManager::instance = nullptr;
QMutex ProjectManager::mutex(QMutex::Recursive);


QPointer<ProjectManager> ProjectManager::getInstance() {
    QMutexLocker lock(&mutex);
    if (instance == nullptr) {
        instance = new ProjectManager();
    }
    return instance;
}


bool ProjectManager::createProject(QString folder)
{
    QMutexLocker lock(&mutex);

    closeProject();

    QFileInfo fi(folder);
    QString projectName = fi.fileName();

    Project project;
    project.name = projectName.toStdString();

    json j = project;
    std::string jsonStr = j.dump(4);
    
    // 指定文件路径
    QDir dir(folder);
    QString filePath = dir.filePath("project.json");
    QFile file(filePath);

    if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) {
        return false;
    }
    QTextStream out(&file);
    out << QString::fromStdString(jsonStr);
    file.close();

    // 创建mission、map、download文件夹
    dir.mkpath(QString::fromStdString(project.missionConfig.folder));
    dir.mkpath(QString::fromStdString(project.downloadConfig.folder));
    dir.mkpath(QString::fromStdString(project.mapConfig.folder));

    projectFolder = folder;

    loadProjectData();

    emit projectCreated(projectData);
    return true;
}


bool ProjectManager::openProject(QString folder)
{
    QMutexLocker lock(&mutex);

    closeProject();
    // 检查folder下是否有project.json
    QDir dir(folder);
    QString filePath = dir.filePath("project.json");
    QFile file(filePath);
    QTextStream in(&file);
    if(!file.open(QIODevice::ReadOnly)) { 
        return false;
    }
    QString jsonStr = in.readAll(); 
    file.close();
    json j = json::parse(jsonStr.toStdString());
    Project project = j.get<Project>();

    // 确保mission、map、download文件夹存在
    dir.mkpath(QString::fromStdString(project.missionConfig.folder));
    dir.mkpath(QString::fromStdString(project.downloadConfig.folder));
    dir.mkpath(QString::fromStdString(project.mapConfig.folder));

    // 设置projectFolder变量
    projectFolder = folder;

    loadProjectData();
    emit projectOpened(projectData);
    return true;
}


bool ProjectManager::saveProject()
{
    QMutexLocker lock(&mutex);
    // 检查projectFolder变量是否有设置
    if (projectFolder.isEmpty()) {
        return false;
    }

    // std::ostringstream sstm;
    // sstm << "projectSaved";
    // RVIZ_COMMON_LOG_INFO(sstm.str().c_str());

    emit projectSaved(projectData);

    saveProjectData();
    return true;
}


bool ProjectManager::closeProject()
{
    QMutexLocker lock(&mutex);
    // 检查projectFolder变量是否有设置
    if (projectFolder.isEmpty()) {
        return false;
    }
    emit projectClosed(projectData);

    (*projectData).clear();
    projectFolder.clear();
    return true;
}


void ProjectManager::loadProjectData()
{
    if(projectData.isNull()) {
        projectData = QSharedPointer<QVariantMap>::create();
    }

    (*projectData).clear();

    (*projectData)["projectDir"] = projectFolder;

    QString projectFile = projectFolder + "/project.json";

    {
        std::ostringstream sstm;
        sstm << "projectFile:" << projectFile.toStdString();
        RVIZ_COMMON_LOG_INFO(sstm.str().c_str());
    }

    Project project = readFromFile<Project>(projectFile);
    (*projectData)["project"] = QVariant::fromValue(project);


    QString waypointsFile = projectFolder + "/" + QString::fromStdString(project.missionConfig.folder) + "/" + QString::fromStdString(project.missionConfig.waypointsFile);
    
    {
        std::ostringstream sstm;
        sstm << "waypointsFile:" << waypointsFile.toStdString();
        RVIZ_COMMON_LOG_INFO(sstm.str().c_str());
    }
    
    Poses waypoints = readFromFile<Poses>(waypointsFile);
    (*projectData)["waypoints"] = QVariant::fromValue(waypoints);

    {
        std::ostringstream sstm;
        sstm << "waypoints size:" << waypoints.poses.size();
        RVIZ_COMMON_LOG_INFO(sstm.str().c_str());
    }

    QString safeAreasFile = projectFolder + "/" + QString::fromStdString(project.missionConfig.folder) + "/" + QString::fromStdString(project.missionConfig.safeAreasFile);
    Flyzones safeAreas = readFromFile<Flyzones>(safeAreasFile);
    (*projectData)["safeAreas"] = QVariant::fromValue(safeAreas);

    QString limitAreasFile = projectFolder + "/" + QString::fromStdString(project.missionConfig.folder) + "/" + QString::fromStdString(project.missionConfig.limitAreasFile);
    Flyzones limitAreas = readFromFile<Flyzones>(limitAreasFile);
    (*projectData)["limitAreas"] = QVariant::fromValue(limitAreas);

    QString photoPointsFile = projectFolder + "/" + QString::fromStdString(project.missionConfig.folder) + "/" + QString::fromStdString(project.missionConfig.photoPointsFile);
    PointNormals photoPoints = readFromFile<PointNormals>(photoPointsFile);
    (*projectData)["photoPoints"] = QVariant::fromValue(photoPoints);

    QString photoPlanesFile = projectFolder + "/" + QString::fromStdString(project.missionConfig.folder) + "/" + QString::fromStdString(project.missionConfig.photoPlanesFile);
    Planes photoPlanes = readFromFile<Planes>(photoPlanesFile);
    (*projectData)["photoPlanes"] = QVariant::fromValue(photoPlanes);
}


void ProjectManager::saveProjectData()
{
    QVariant projectVar = (*projectData)["project"];
    Project project = projectVar.value<Project>();

    QVariant waypointsVar = (*projectData)["waypoints"];
    Poses waypoints = waypointsVar.value<Poses>();
    QString waypointsFile = projectFolder + "/" + QString::fromStdString(project.missionConfig.folder) + "/" + QString::fromStdString(project.missionConfig.waypointsFile);
    writeToFile(waypointsFile, waypoints);

    QVariant safeAreasVar = (*projectData)["safeAreas"];
    Flyzones safeAreas = safeAreasVar.value<Flyzones>();
    QString safeAreasFile = projectFolder + "/" + QString::fromStdString(project.missionConfig.folder) + "/" + QString::fromStdString(project.missionConfig.safeAreasFile);
    writeToFile(safeAreasFile, safeAreas);

    QVariant limitAreasVar = (*projectData)["limitAreas"];
    Flyzones limitAreas = limitAreasVar.value<Flyzones>();
    QString limitAreasFile = projectFolder + "/" + QString::fromStdString(project.missionConfig.folder) + "/" + QString::fromStdString(project.missionConfig.limitAreasFile);
    writeToFile(limitAreasFile, limitAreas);

    QVariant photoPointsVar = (*projectData)["photoPoints"];
    PointNormals photoPoints = photoPointsVar.value<PointNormals>();
    QString photoPointsFile = projectFolder + "/" + QString::fromStdString(project.missionConfig.folder) + "/" + QString::fromStdString(project.missionConfig.photoPointsFile);
    writeToFile(photoPointsFile, photoPoints);

    QVariant photoPlanesVar = (*projectData)["photoPlanes"];
    Planes photoPlanes = photoPlanesVar.value<Planes>();
    QString photoPlanesFile = projectFolder + "/" + QString::fromStdString(project.missionConfig.folder) + "/" + QString::fromStdString(project.missionConfig.photoPlanesFile);
    writeToFile(photoPlanesFile, photoPlanes);

}


}


}